From 499ef041a5726dc4745b8e5ec174b4d7d2e80674 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 27 Jun 2006 18:08:46 +0100 Subject: [PATCH] [LINUX][BLKBACK] Support temporary disconnection from frontend. Signed-off-by: Steven Smith Signed-off-by: Keir Fraser --- .../drivers/xen/blkback/common.h | 1 + .../drivers/xen/blkback/interface.c | 22 ++++++++++++++----- .../drivers/xen/blkback/xenbus.c | 6 +++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index 0ba7c588dd..d057f79242 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -95,6 +95,7 @@ typedef struct blkif_st { } blkif_t; blkif_t *blkif_alloc(domid_t domid); +void blkif_disconnect(blkif_t *blkif); void blkif_free(blkif_t *blkif); int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index 8f1bf4d2fe..e5d67ea633 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -32,6 +32,7 @@ #include "common.h" #include +#include static kmem_cache_t *blkif_cachep; @@ -139,22 +140,33 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) return 0; } -void blkif_free(blkif_t *blkif) +void blkif_disconnect(blkif_t *blkif) { + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + blkif->xenblkd = NULL; + } + atomic_dec(&blkif->refcnt); wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); + atomic_inc(&blkif->refcnt); - /* Already disconnected? */ - if (blkif->irq) + if (blkif->irq) { unbind_from_irqhandler(blkif->irq, blkif); - - vbd_free(&blkif->vbd); + blkif->irq = 0; + } if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); + blkif->blk_ring.sring = NULL; } +} +void blkif_free(blkif_t *blkif) +{ + if (!atomic_dec_and_test(&blkif->refcnt)) + BUG(); kmem_cache_free(blkif_cachep, blkif); } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 5c4233d249..5ee3a46982 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -105,9 +105,10 @@ static int blkback_remove(struct xenbus_device *dev) kfree(be->backend_watch.node); be->backend_watch.node = NULL; } + if (be->blkif) { - if (be->blkif->xenblkd) - kthread_stop(be->blkif->xenblkd); + blkif_disconnect(be->blkif); + vbd_free(&be->blkif->vbd); blkif_free(be->blkif); be->blkif = NULL; } @@ -273,6 +274,7 @@ static void frontend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: + blkif_disconnect(be->blkif); xenbus_switch_state(dev, XenbusStateClosing); break; -- 2.30.2